package org.lmaor.menu.entry;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public abstract class Menu<T> {
	private Menu<T> root = this;
	private String path = "";
	private String name = "";
	private Map<String, Menu<T>> childNodes = new ConcurrentHashMap<String, Menu<T>>();
	private Menu<T> parent;
	private T value;
	private boolean autoDir = false;
	
	protected void setAutoDir(boolean autoDir){
		this.autoDir = autoDir;
	}
	public Menu<T> createAndGet(String path){
		Menu<T> menu = create();
		if(add(path, menu)){
			return menu;
		}else{
			return get(path);
		}
	}
	/** 在这个路径下添加Menu，如果存在则不可被覆盖
	 * 
	 * @param path
	 * @param menu
	 * @return
	 */
	public boolean add(String path,Menu<T> menu){
		if(!this.getClass().isAssignableFrom(menu.getClass())){
			return false;
		}
		Menu<T> cm = findDirAndCreateDir(path);// 查找插入到哪个节点
		Map<String, Menu<T>> childNodes = cm.childNodes; // 获得这个节点的孩子存储MAP
		String name = getPathName(path);
		Menu<T>dirMenu = childNodes.get(name);
		
		if(dirMenu != null){
			if(!dirMenu.autoDir){ // 如果不是自动生成的目录元素则不可以覆盖
				return false;
			}
			menu.childNodes.putAll(dirMenu.childNodes);
		}
		
		menu.path = getCPath(cm.path,name); // 设置新元素的path
		menu.parent = cm; // 设置父亲元素
		menu.root = root; // 设置根元素
		childNodes.put(name, menu);
		addListener(menu);
		return true;
	}
	
	public boolean add(String path,String name,T value){
		Menu<T> menu = create();
		menu.setName(name).setValue(value);
		return this.add(path, menu);
	}
	/** 删除这个路径的
	 * 
	 * @param path
	 * @return
	 */
	public Menu<T> remove(String path){
		Menu<T> cm = findDirAndCreateDir(path);
		String childMenuPath = getPathName(path);
		Menu<T> result = cm.childNodes.remove(childMenuPath);
		
		if(result!=null&&result.autoDir){
			return null;
		}else{
			removeListener(result);
			return result;
		}
	}
	/** 删除当前
	 * 
	 */
	public void removeCurrent(){
		if(parent==null){
			return;
		}
		parent.remove(getPathName(this.path));
	}
	
	public Menu<T> get(String path){
		Menu<T> cm = findDirAndCreateDir(path);
		if(cm == null){
			return null;
		}
		
		String childMenuPath = getPathName(path);
		Menu<T> result = cm.childNodes.get(childMenuPath);
		
		if(result!=null&&result.autoDir){
			return null;
		}else{
			getListener(result);
			return result;
		}
	}
	public List<Menu<T>> getAllChildMenus(){
		List<Menu<T>> result = new ArrayList<Menu<T>>();
		List<Menu<T>> qs = new ArrayList<Menu<T>>();
		qs.add(this);
		for (int i = 0; i < qs.size(); i++) {
			Menu<T> cm = qs.get(i);
			Map<String, Menu<T>> childNodes = cm.childNodes;
			for(Entry<String, Menu<T>> entry : childNodes.entrySet()){
				Menu<T> c = entry.getValue();
				if(!c.autoDir){
					result.add(c);
				}
				qs.add(c);
			}
		}
		return result;
	}
	public List<String> getAllChildMenuPaths(){
		List<Menu<T>> cms = getAllChildMenus();
		List<String> paths = new ArrayList<String>(cms.size());
		for (Menu<T> cm : cms) {
			paths.add(cm.getPath());
		}
		return paths;
	}
	private String getPathName(String path){
		int x = path.lastIndexOf("/");
		if(x == path.length() - 1){
			x = path.lastIndexOf("/", x-1);
			return path.substring(x+1,path.length() - 1);
		}else{
			return path.substring(x+1);
		}
	}
	private Menu<T> findDirAndCreateDir(String path){
		return findDirAndCreateDir(path, true);
	}
	private String getCPath(String path,String cname){
		if(path.equals("/")){
			return "/"+cname;
		}else{
			return path+"/"+cname;
		}
	}
	// 查询目录并且创建目录
	private Menu<T> findDirAndCreateDir(String path,boolean create){
		if(path==null||path.length() == 0||path.equals("/")){
			return root;
		}
		String childMenuPaths[] = path.split("/");
		Menu<T> cm = null; // 设置从哪开始查询
		if(path.startsWith("/")){ // 如果开头为/ 则从根开始查询
			cm = root;
		}else{
			cm = this;
		}
		
		for (int i = 0; i < childMenuPaths.length-1; i++) {
			Map<String, Menu<T>> childNodes = cm.childNodes;
			String childMenuPath = childMenuPaths[i];
			String cpath = cm.path+"/"+childMenuPath;
			cm = childNodes.get(childMenuPath);
			Menu<T> p = cm;
			if(cm == null){ // 自动创建一个目录
				if(create){
					cm = create();
					cm.path = cpath;
					cm.autoDir = true;
					cm.root = root;
					cm.name = childMenuPath;
					cm.parent = p;
					childNodes.put(childMenuPath, cm);
				}else{
					break;
				}
			}
		}
		return cm;
	}
	
	public Menu<T> setValue(T value) {
		this.value = value;
		return this;
	}
	public T getValue() {
		return value;
	}
	public T getValue(String path) {
		Menu<T> menu = get(path);
		if(menu == null){
			return null;
		}else{
			return menu.getValue();
		}
	}
	public Menu<T> setName(String name) {
		this.name = name;
		return this;
	}
	public String getName() {
		return name;
	}
	public String getName(String path) {
		Menu<T> menu = get(path);
		if(menu == null){
			return null;
		}else{
			return menu.getName();
		}
	}
	
	public Menu<T> getParent() {
		return parent;
	}
	public Menu<T> getRoot() {
		return root;
	}
	public String getPath() {
		return path;
	}
	/** 成功添加后会调用
	 * 
	 * @param menu
	 */
	protected void addListener(Menu<T> menu){
		
	}
	protected void getListener(Menu<T> menu){
		
	}
	/** 成功删除后会调用
	 * 
	 * @param menu
	 */
	protected void removeListener(Menu<T> menu){
		
	}
	/** 创建menu的方式
	 * 
	 * @return
	 */
	public abstract Menu<T> create();
	
	public boolean isDir(){
		return autoDir;
	}
	/** 将目录转为文件
	 * 
	 * @param name
	 * @param value
	 */
	public void dirToFileInit(String name,T value){
		if(autoDir){
			autoDir = false;
			this.name = name;
			this.value = value;
			
		}
	}
}
